package com.mallcai.bigdata.ladon.service.common.impl;

import com.google.common.base.Preconditions;
import com.mallcai.bigdata.ladon.config.ApplicationContextProvider;
import com.mallcai.bigdata.ladon.datasource.AbstractJdbcHandler;
import com.mallcai.bigdata.ladon.datasource.HandlerFactory;
import com.mallcai.bigdata.ladon.dpl.entity.common.Datasource;
import com.mallcai.bigdata.ladon.dpl.mapper.common.DatasourceMapper;
import com.mallcai.bigdata.ladon.dpl.mapper.peekdata.ModelMapper;
import com.mallcai.bigdata.ladon.service.common.IDatasourceService;
import com.mallcai.bigdata.ladon.service.report.impl.MetaRefreshEvent;
import com.mallcai.bigdata.ladon.service.system.IMailService;
import com.mallcai.bigdata.ladon.utils.DataSourceUtils;
import com.mallcai.bigdata.ladon.utils.SqlUtils;
import com.mallcai.bigdata.ladon.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by oneape<oneape15@163.com>
 * Created 2019-05-27 17:15.
 * Modify:
 */
@Slf4j
@Service
public class DatasourceService implements IDatasourceService {

    @Autowired
    private DatasourceMapper datasourceMapper;
    @Autowired
    private ModelMapper      modelMapper;
    @Autowired
    private IMailService     iMailService;

    /**
     * 添加数据源
     *
     * @param datasource Datasource
     * @return int 1 - 成功; 0 - 失败;
     */
    @Override
    public int addDatasource(Datasource datasource) {
        return datasourceMapper.insert(datasource);
    }

    /**
     * 修改数据源
     *
     * @param datasource Datasource
     * @return int 1 - 成功; 0 - 失败;
     */
    @Override
    public int editDatasource(Datasource datasource) {
        int status =  datasourceMapper.update(datasource);
        if(status > 0){
            ApplicationContextProvider.publishEvent(MetaRefreshEvent.newDatasourceChangeEvent(datasource.getId()));
        }
        return status;
    }

    /**
     * 判断数据源是否正在使用中
     *
     * @param dsId Long
     * @return boolean
     */
    @Override
    public boolean isUsing(Long dsId) {
        int size = modelMapper.getSizeOfDatasource(dsId);
        return size > 0;
    }

    /**
     * 删除数据源
     *
     * @param datasource Datasource
     * @return int 1 - 成功; 0 - 失败;
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteDatasource(Datasource datasource) {
        int status = datasourceMapper.delete(datasource);

        if (status > 0 && datasource.getId() != null) {
            ApplicationContextProvider.publishEvent(MetaRefreshEvent.newDatasourceChangeEvent(datasource.getId()));
        }
        return status;
    }

    /**
     * 根据条件查询数据源
     *
     * @param params Map
     * @return List
     */
    @Override
    public List<Datasource> getByParams(Map<String, Object> params) {
        return datasourceMapper.getByParams(params);
    }

    /**
     * 根据Id查询数据源
     *
     * @param id Long 数据id
     * @return Datasource
     */
    @Override
    public Datasource getById(Long id) {
        return datasourceMapper.getById(id);
    }

    /**
     * 获取指定数据源的所有表结构
     *
     * @param dsId Long   数据源Id
     * @return List
     */
    @Override
    public List<TableVo> getAllTables(Long dsId) {
        List<TableVo> tables = new ArrayList<>();

        Datasource ds = getById(dsId);
        if (ds == null) {
            return tables;
        }
        AbstractJdbcHandler handler = HandlerFactory.getHandler(ds);

        if (handler == null) {
            return tables;
        }

        tables = handler.getAllTables(ds);

        return tables;
    }

    /**
     * 获取指定数据源下面的表的字段列表
     *
     * @param dsId      Long   数据源Id
     * @param tableName String
     * @return List
     */
    @Override
    public List<ColumnVo> getTableColumns(Long dsId, String tableName) {
        List<ColumnVo> columns = new ArrayList<>();

        Datasource ds = getById(dsId);
        if (ds == null) {
            return columns;
        }

        AbstractJdbcHandler handler = HandlerFactory.getHandler(ds);
        if (handler == null) {
            return columns;
        }

        columns = handler.getColumns(ds, tableName);

        return columns;
    }

    /**
     * 执行Sql获取结果
     *
     * @param dsId  Long 数据源Id
     * @param param QueryParam 查询条件
     * @return DataVo
     */
    @Override
    public DataVo execSql(Long dsId, QueryParam param) {
        Datasource ds = Preconditions.checkNotNull(getById(dsId),"模型依赖的数据源不存在!");
        return execSql(ds, param);
    }

    /**
     * 执行Sql获取结果
     *
     * @param ds    Datasource
     * @param param QueryParam 查询条件
     * @return DataVo
     */
    @Override
    public DataVo execSql(Datasource ds, QueryParam param) {
        if (ds == null) {
            return null;
        }

        AbstractJdbcHandler handler = HandlerFactory.getHandler(ds);
        if (handler == null) {
            return null;
        }

        return handler.executeSql(ds, param);
    }

    /**
     * 异步导出数据到邮箱中
     *
     * @param ds    Datasource 数据源信息
     * @param param ExportParam 导出参数
     * @return int
     */
    @Override
    public int asynSendData2Email(Datasource ds, ExportParam param) {
        if (ds == null) {
            return 0;
        }

        AbstractJdbcHandler handler = HandlerFactory.getHandler(ds);
        if (handler == null) {
            return 0;
        }
        return handler.exportData2Email(ds, param, iMailService);
    }


    @Override
    public void execute(Long dsId, QueryParam param) {
        Datasource ds = Preconditions.checkNotNull(getById(dsId),"模型依赖的数据源不存在!");
        AbstractJdbcHandler handler = getHandler(ds);
        if(handler != null){
            handler.execute(ds, param);
        }
    }

    private AbstractJdbcHandler getHandler(Datasource ds){
        if (ds == null) {
            return null;
        }
        return HandlerFactory.getHandler(ds);
    }

    @Override
    public <T> int[][] batchUpdate(Long dsId, BatchUpdateParam<T> batchUpdateParam) {
        Datasource ds = Preconditions.checkNotNull(getById(dsId),"模型依赖的数据源不存在!");
        AbstractJdbcHandler handler = getHandler(ds);
        if(handler != null){
           return handler.batchUpdate(ds, batchUpdateParam);
        }
        return null;
    }

    @Override
    public boolean test(Datasource datasource) {
        return DataSourceUtils.test(datasource);
    }
}
